/**
 * @author zcz
 * @class Ext.ux.form
 * 版本
 * @version 1
 */

Ext.ux.form = Ext.extend(Ext.util.Observable, {
    /**qtip,title,under,side**/
    msgTarget: 'right',
    validateEvent: 'blur',
    easing: 'elasticOut',
    params: {},
    url: '',
    valid: false,
    method: 'post',
    filed: null,
    success: function(){},
    failure: function(){},
    emptyFn: function(){},
    constructor: function(config){
        this.config = config || {};
        Ext.apply(this, config);
        
        Ext.ux.form.superclass.constructor.call(this, config);
        
        if (this.form) {
            if (typeof this.form == "string") {
                this.form = Ext.get(this.form);
                this.id = this.form.dom.id || Ext.id;
            }
            if (this.form.dom.action) {
                this.url = this.form.dom.action;
            }
            
            if (this.form.dom.method) {
                this.method = this.form.dom.method;
            }
            
            this.initializes();
            this.form.on('submit', function(evt, element, opts){
                evt.preventDefault();
                this.formSubmit();
            }, this);
            this.form.on('reset', function(evt, element, opts){
                this.clearAllInvalid();
            }, this);
        }
        else {
            return false;
        }
    },
    initializes: function(){
        Ext.each(this.form.dom.elements, function(items, index, allItems){
            this.filed = items;
            var el = Ext.get(this.filed);
            var tagName = '', type = '';
            tagName = el.dom.tagName.toString().toLowerCase();
            type = el.dom.type.toString().toLowerCase();
            if (tagName != 'button' && type != "submit" && type != "reset") {
                el.addListener(this.validateEvent, function(){
                    this.emptyFn();
                    if (el.getAttribute('allowBlank')) {
                        this.isAllowBlank(el);
                    }
                    
                    if (el.getAttribute('vtype')) {
                        this.isVtype(el);
                    }
                    
                    if (el.getAttribute('regex')) {
                        this.isRegex(el);
                    }
                    
                    if (el.getAttribute('matched')) {
                        this.isMatch(el);
                    }
                    
                    if (el.getAttribute('minLen')) {
                        this.isMinLength(el);
                    }
                    
                    if (el.getAttribute('maxLen')) {
                        this.isMaxLength(el);
                    }
                }, this);
            }
        }, this);
    },
    isValid: function(){
        var valid = true,valids = [],_valid;
        Ext.each(this.form.dom.elements, function(items, index, allItems){
            this.filed = items;
            var el = Ext.get(this.filed);
            this.emptyFn();
            
            if (this.filed.getAttribute('allowBlank')) {
                _valid = this.isAllowBlank(el);
                valids.push(_valid);
            }
            
            if (this.filed.getAttribute("vtype")) {
                _valid = this.isVtype(el);
                valids.push(_valid);
            }
            
            if (this.filed.getAttribute("regex")) {
                _valid = this.isRegex(el);
                valids.push(_valid);
            }
            
            if (el.getAttribute('matched')) {
                _valid = this.isMatch(el);
                valids.push(_valid);
            }
            
            if (el.getAttribute('minLen')) {
                _valid = this.isMinLength(el);
                valids.push(_valid);
            }
            
            if (el.getAttribute('maxLen')) {
                _valid = this.isMaxLength(el);
                valids.push(_valid);
            }
        }, this);
        var len = valids.length;
        for(var i = 0;i < len;i++){
            if(!valids[i]){
                valid = false;
            }
        }
        return valid;
    },
    isAllowBlank: function(el){
        var valid = true;
        var error = el.getAttribute('blankText') ? el.getAttribute('blankText').toString() : Ext.ux.VTypes["blankText"];
        
        if (el.getAttribute("allowBlank").toString() == "false") {
            if (!Ext.trim(el.getValue())) {
                var trigger = Ext.query('div[trigger=' + el.id + ']');
                if (trigger.length == 0) {
                    this.validateTips(el, error);
                }
                valid = false;
            }
            else {
                this.clearInvalid(el);
            }
            return valid;
        }
    },
    isVtype: function(el){
        var valid = true;
        var vtype = el.getAttribute("vtype").toString();
        var vtypeFn = Ext.ux.VTypes[vtype];
        var vtypeMsg = Ext.ux.VTypes[vtype + "Text"];
        
        if (Ext.trim(el.getValue())) {
            if (!vtypeFn.call(el, Ext.trim(el.getValue()))) {
                var trigger = Ext.query('div[trigger=' + el.id + ']');
                if (trigger.length == 0) {
                    this.validateTips(el, vtypeMsg);
                }
                valid = false;
            }
            else {
                this.clearInvalid(el);
            }
        }
        else {
            valid = false;
        }
        return valid;
    },
    isRegex: function(el){
        var regTxt = el.getAttribute('regexText') ? el.getAttribute('regexText').toString() : '';
        var regex = el.getAttribute('regex');
        var valid = true;
        if (Ext.trim(el.getValue())) {
            if (regex) {
                if (!eval(regex).test(Ext.trim(el.getValue()))) {
                    var trigger = Ext.query('div[trigger=' + el.id + ']');
                    if (trigger.length == 0) {
                        this.validateTips(el, regTxt);
                    }
                    valid = false;
                }
                else {
                    this.clearInvalid(el);
                }
            }
        }
        else {
            valid = false;
        }
        return valid;
    },
    isMatch: function(el){
        var valid = true;
        var vtype = el.getAttribute("vtype").toString();
        var vtypeFn = Ext.ux.VTypes[vtype];
        var vtypeMsg = el.getAttribute('matchText') ? el.getAttribute("matchText").toString() : Ext.ux.VTypes[vtype + "Text"];
        
        if (Ext.trim(el.getValue())) {
            if (!vtypeFn.call(el, Ext.trim(el.getValue()))) {
                var trigger = Ext.query('div[trigger=' + el.id + ']');
                if (trigger.length == 0) {
                    this.validateTips(el, vtypeMsg);
                }
                valid = false;
            }
            else {
                this.clearInvalid(el);
            }
        }
        else {
            valid = false;
        }
        return valid;
    },
    isMinLength: function(el){
        var valid = true;
        var minLen = el.getAttribute("minLen").toString();
        var minLenText = el.getAttribute("minLenText") ? el.getAttribute("minLenText").toString() : Ext.ux.VTypes["minLenText"];
        if(!el.getAttribute("minLenText")) {
            minLenText = String.format(minLenText,minLen);
        }
        var val = Ext.trim(el.getValue());
        if (val) {
            if (val.length < minLen) {
                var trigger = Ext.query('div[trigger=' + el.id + ']');
                if (trigger.length == 0) {
                    this.validateTips(el, minLenText);
                }
                valid = false;
            }
            else {
                this.clearInvalid(el);
            }
        }
        else {
            valid = false;
        }
        return valid;
    },
    isMaxLength:function(el){
        var valid = true;
        var maxLen = el.getAttribute("maxLen").toString();
        var maxLenText = el.getAttribute("maxLenText") ? el.getAttribute("maxLenText").toString() : Ext.ux.VTypes["maxLenText"];
        if(!el.getAttribute("maxLenText")) {
            maxLenText = String.format(maxLenText,maxLen);
        }
        var val = Ext.trim(el.getValue());
        if (val) {
            if (val.length > maxLen) {
                var trigger = Ext.query('div[trigger=' + el.id + ']');
                if (trigger.length == 0) {
                    this.validateTips(el, maxLenText);
                }
                valid = false;
            }
            else {
                this.clearInvalid(el);
            }
        }
        else {
            valid = false;
        }
        return valid;
    },
    validateTips: function(el, msg){
        var easing = this.easing;
        var tipsMsg = new Ext.ux.tips({
            msgCls: 'Ext-ux-tips-message',
            traffic: 'error',
            trigger: el,
            message: msg,
            autoDestroy: false,
            formTips: true,
            easing: easing
        });
    },
    clearInvalid: function(el){
        var trigger = Ext.query('div[trigger=' + el.id + ']');
        Ext.get(trigger).remove();
    },
    clearAllInvalid: function(){
        Ext.each(this.form.dom.elements, function(itmes, index, allItems){
            var el = Ext.get(itmes);
            this.clearInvalid(el);
        }, this);
    },
    formSubmit: function(){
        if (this.isValid()) {
            this.params = this.getValues();
            Ext.Ajax.request({
                url: this.url,
                method: this.method,
                params: this.params,
                success: function(response, opts){
                    var response = Ext.decode(response.responseText);
                    this.formReset();
                    this.form.dom.reset();
                    this.success(this.form, response);
                },
                failure: function(response, opts){
                    var response = Ext.decode(response.responseText);
                    this.formReset();
                    this.form.dom.reset();
                    this.failure(this.form, response);
                },
                scope: this
            });
        }
        else {
            return false;
        }
    },
    formReset: function(){
        this.clearAllInvalid();
    },
    getValues: function(){
        return Ext.urlDecode(Ext.Ajax.serializeForm(this.form.dom));
    }
});
